#pragma once

#include <pthread.h>

class Cond
{
public:
    Cond(pthread_mutex_t *pmutex) : _pmutex(pmutex)
    {
        pthread_cond_init(&_cond, nullptr);
    }

    void wait()
    {
        pthread_cond_wait(&_cond, _pmutex);
    }

    void signal()
    {
        pthread_cond_signal(&_cond);
    }

    void broadcast()
    {
        pthread_cond_broadcast(&_cond);
    }

    ~Cond()
    {
        pthread_cond_destroy(&_cond);
    }

private:
    pthread_mutex_t *_pmutex;
    pthread_cond_t _cond;
};

class Lock
{
public:
    Lock()
    {
        pthread_mutex_init(&_pmutex, nullptr);
    }

    ~Lock()
    {
        pthread_mutex_destroy(&_pmutex);
    }

    void lock()
    {
        pthread_mutex_lock(&_pmutex);
    }

    void unlock()
    {
        pthread_mutex_unlock(&_pmutex);
    }

    pthread_mutex_t *ret_mutex()
    {
        return &_pmutex;
    }

private:
    pthread_mutex_t _pmutex;
};

class LockGuard
{
public:
    LockGuard(Lock *pmutex) : _pmutex(pmutex)
    {
        _pmutex->lock();
    }

    ~LockGuard()
    {
        _pmutex->unlock();
    }

private:
    Lock *_pmutex;
};

class LockGuard_static
{
public:
    LockGuard_static(pthread_mutex_t *pmutex) : _pmutex(pmutex)
    {
        pthread_mutex_lock(_pmutex);
    }

    ~LockGuard_static()
    {
        pthread_mutex_unlock(_pmutex);
    }

private:
    pthread_mutex_t *_pmutex;
};

// class Lock_static
// {
// public:
//     Lock_static()
//     {}

//     ~Lock_static()
//     {
//         pthread_mutex_destroy(&_pmutex);
//     }

//     void lock()
//     {
//         pthread_mutex_lock(&_pmutex);
//     }

//     void unlock()
//     {
//         pthread_mutex_unlock(&_pmutex);
//     }

//     pthread_mutex_t* ret_mutex()
//     {
//         return &_pmutex;
//     }
// private:
//     static pthread_mutex_t _pmutex;
// };

// pthread_mutex_t Lock_static::_pmutex = PTHREAD_MUTEX_INITIALIZER;

// class LockGuard_static
// {
// public:
//     LockGuard_static(Lock_static *pmutex) : _pmutex(pmutex)
//     {
//         _pmutex->lock();
//     }

//     ~LockGuard_static()
//     {
//         _pmutex->unlock();
//     }

// private:
//     Lock_static *_pmutex;
// };

